%%--------------------------------------------------------------------
%% Author: <vjache>
%% Created: 30.03.2009
%% Description: Iterator over all keys in an ets table.
%%--------------------------------------------------------------------
-module(iter_disk_log).

%%--------------------------------------------------------------------
%% Include files
%%--------------------------------------------------------------------
-include("../include/iter.hrl").
%%--------------------------------------------------------------------
%% Exported Functions
%%--------------------------------------------------------------------
-export([
		 new/1,
		 new/3,
		 open/1,
		 next/1,
		 close/1,
		 test/0
		 ]).

%%--------------------------------------------------------------------
%% API Functions
%%--------------------------------------------------------------------

new(Log,OpenFun,CloseFun) when 
  is_function(OpenFun, 1),
  is_function(CloseFun, 1) ->
	iter:from_module(?MODULE, {Log,OpenFun,CloseFun}).
new(ArgL) when is_list(ArgL)->
	iter:from_module(?MODULE, ArgL).

open({Log,OpenFun,CloseFun}) when
  is_function(OpenFun, 1),
  is_function(CloseFun, 1) ->
	OpenFun(Log),
	{Log,start,[],CloseFun};
open({opened,Log}) ->
	{Log,start,[],noclose};
open(ArgL) ->
	case disk_log:open(ArgL) of
		{error,_}=Err ->
			exit(Err);
		{repaired, _, _, _} ->
			ok;
		{ok,_} ->
			ok
	end,
	case lists:keysearch(name, 1, ArgL) of
		false ->
			exit({log_name_absent,ArgL});
		{value,{name,Log}} ->
			case (catch cache_ets:get(?MODULE, Log,nocache)) of
				nocache ->
					cache_ets:put(?MODULE, Log,1);
				{'EXIT',{badarg,_}} ->
					cache_ets:cleanup(?MODULE),
					cache_ets:put(?MODULE, Log,1);
				_ ->
					cache_ets:update_counter(?MODULE, Log,1)
			end,
			{Log,start,[],autoclose}
	end.

next({Log,Cont,[],CloseFlag}=S) ->
	case disk_log:chunk(Log, Cont, 1000) of
		{NewCont, Terms, _Badbytes} ->
			next({Log,NewCont,Terms,CloseFlag});
		eof ->
			{S,?EOF};
		{error,Reason} ->
			throw({disk_log_error,Reason,Log});
		{NewCont,Terms} ->
			next({Log,NewCont,Terms,CloseFlag})
	end;
next({Log,Cont,[Item|RestTerms],CloseFlag}) ->
	{{Log,Cont,RestTerms,CloseFlag},Item}.
close({Log,_Cont,_Terms,CloseFlag}) ->
	case CloseFlag of
		noclose ->
			ok;
		autoclose ->
			case cache_ets:update_counter(?MODULE, Log, -1) of
				0 ->
					ok=disk_log:close(Log);
				Cnt when Cnt>0 ->
					ok
			end;
		CloseFun when is_function(CloseFun,1) ->
			CloseFun(Log)
	end.

%%--------------------------------------------------------------------
%% Test Functions
%%--------------------------------------------------------------------

test() ->
	I=new([{name,"TestLog"}]),
	iter:foreach(I,fun(E)->
						   io:format("~p~n",[E])
				 end),
	ok.

%%--------------------------------------------------------------------
%% Local Functions
%%--------------------------------------------------------------------